package com.system.uitls;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;

public class ChartUtils
{
  private String sum;
  private String name;
  private String sql;
  private List<String> categories = new ArrayList();

  public String getSum() {
    return this.sum;
  }

  public void setSum(String sum) {
    this.sum = sum;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List<String> getCategories() {
    return this.categories;
  }

  public void setCategories(List<String> categories) {
    this.categories = categories;
  }

  public String getSql() {
    return this.sql;
  }

  public void setSql(String sql) {
    this.sql = sql;
  }

  public static List<Object[]> parsePieData(String type, List<Map<String, Object>> list)
  {
    if ((StringUtils.isBlank(type)) || (list == null))
    {
      return null;
    }

    List result = new ArrayList();

    Map map = new HashMap();

    for (Map m : list)
    {
      map.put(m.get(type).toString(), Float.valueOf(Float.parseFloat(m.get("_Total").toString())));
    }

    float total = ((Float)map.get("_Total")).floatValue();

    map.remove("_Total");
    Entry entry;
    for (Object o : map.entrySet())
    {
      entry = (Entry) o;
      result.add(new Object[] { entry.getKey(), Float.valueOf(((Float)entry.getValue()).floatValue() / total) });
    }

    return result;
  }

  public static List<Map<String, Object>> parseLineOrColumnData(String type, List<Map<String, Object>> list)
  {
    if ((StringUtils.isBlank(type)) || (list == null))
    {
      return null;
    }
    List result = new ArrayList();

    for (Map m : list)
    {
      if ("_Total".equals(m.get(type).toString()))
        continue;
      Map obj = new HashMap(2);
      List data = new ArrayList();
      Entry entry;
      for (Object o : m.entrySet())
      {
    	entry = (Entry) obj;
        if ("_Total".equals(entry.getKey()))
          continue;
        if (!type.equals(entry.getKey()))
        {
          data.add(Float.valueOf(Float.parseFloat(entry.getValue().toString())));
        }
        else obj.put("name", entry.getValue());

      }

      obj.put("data", data);
      result.add(obj);
    }

    return result;
  }

  public static String parseToComplete(String date, String dateType)
  {
    String result = "";
    if ("year".equals(dateType))
    {
      result = date + "-01-01";
    } else if ("month".equals(dateType))
    {
      result = date + "-01";
    }
    else result = date;

    return result;
  }

  public String generateSql(String dateField, String startDate, String endDate, String dateType)
  {
    if (StringUtils.isBlank(this.sql))
    {
      return "";
    }
    StringBuffer sb = new StringBuffer();

    StringBuffer selectHead = new StringBuffer();
    String countStr = "";
    try {
      countStr = parse(startDate, endDate, dateType, false);
      selectHead.append("select ")
        .append(this.name)
        .append(",isnull([0],0) as '_Total',")
        .append(parse(startDate, endDate, dateType, true));
    } catch (ParseException e) {
      e.printStackTrace();
    }

    String convert = "";
    if (dateType.equals("year"))
    {
      convert = "convert(char(4)," + dateField + ",120)";
    } else if (dateType.equals("month"))
      convert = "convert(char(7)," + dateField + ",120)";
    else {
      convert = "convert(char(10)," + dateField + ",120)";
    }
    this.sql = this.sql.toLowerCase();

    sb.append(selectHead.toString())
      .append(" from(")
      .append(this.sql.substring(0, this.sql.indexOf("from")).replace(this.name, "isnull(" + this.name + ",'_Total') as '" + this.name + "'"))
      .append(", isnull(")
      .append(convert)
      .append(",0) as '_data' ,")
      .append(this.sum)
      .append(" as '_qty' ")
      .append(this.sql.substring(this.sql.indexOf("from"), this.sql.length()));

    if (this.sql.indexOf("group by") > 0)
    {
      sb.append(",").append(convert);
    }
    else sb.append(" group by ").append(convert);

    sb.append(" with cube) ")
      .append("as _temp ")
      .append("pivot(sum(_qty) for _data in ([0],")
      .append(countStr)
      .append(")) as _pvt");

    return sb.toString();
  }

  public static List<String> getCategories(String start, String end, String dateType)
  {
    start = parseToComplete(start, dateType);
    end = parseToComplete(end, dateType);
    List categories = new ArrayList();
    Calendar c1 = Calendar.getInstance();
    c1.set(Integer.parseInt(start.substring(0, 4)), Integer.parseInt(start.substring(5, 7)) - 1, Integer.parseInt(start.substring(8, 10)));

    Calendar c2 = Calendar.getInstance();
    c2.set(Integer.parseInt(end.substring(0, 4)), Integer.parseInt(end.substring(5, 7)) - 1, Integer.parseInt(end.substring(8, 10)));
    try {
      if (dateType.equals("year"))
      {
        int startYear = c1.get(1);
        int endYear = c2.get(1);
        for (; startYear <= endYear; startYear++)
        {
          categories.add(String.valueOf(startYear));
        }
      } else if (dateType.equals("month")) {
        int count = c2.get(1) * 12 + c2.get(2) - (c1.get(1) * 12 + c1.get(2)) + 1;
        for (int i = 0; i < count; i++)
        {
          String month = String.valueOf(c1.get(2) + 1);
          if (month.length() == 1)
          {
            month = "0" + month;
          }
          categories.add(c1.get(1) + "-" + month);
          c1.add(2, 1);
        }
      } else {
        SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
        int count = getIntervalDaysOfExitDate2(fm.parse(start), fm.parse(end));
        for (int i = 0; i < count; i++)
        {
          c1.add(5, 1);
          String month = String.valueOf(c1.get(2) + 1);
          if (month.length() == 1)
          {
            month = "0" + month;
          }

          String day = String.valueOf(c1.get(5));
          if (day.length() == 1)
          {
            day = "0" + day;
          }
          categories.add(c1.get(1) + "-" + month + "-" + day);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    return categories;
  }

  private String parse(String start, String end, String dateType, boolean flag) throws ParseException {
    StringBuffer result = new StringBuffer();

    Calendar c1 = Calendar.getInstance();
    c1.set(Integer.parseInt(start.substring(0, 4)), Integer.parseInt(start.substring(5, 7)) - 1, Integer.parseInt(start.substring(8, 10)));

    Calendar c2 = Calendar.getInstance();
    c2.set(Integer.parseInt(end.substring(0, 4)), Integer.parseInt(end.substring(5, 7)) - 1, Integer.parseInt(end.substring(8, 10)));

    if (dateType.equals("year"))
    {
      int startYear = c1.get(1);
      int endYear = c2.get(1);
      for (; startYear <= endYear; startYear++)
      {
        this.categories.add(String.valueOf(startYear));
        String value = "[" + startYear + "]";
        if (flag)
        {
          result.append("isnull(").append(value).append(",0) as '").append(startYear).append("',");
        }
        else result.append("[").append(startYear).append("]").append(",");
      }
    }
    else if (dateType.equals("month"))
    {
      int count = c2.get(1) * 12 + c2.get(2) - (c1.get(1) * 12 + c1.get(2)) + 1;
      for (int i = 0; i < count; i++)
      {
        String month = String.valueOf(c1.get(2) + 1);
        if (month.length() == 1)
        {
          month = "0" + month;
        }
        this.categories.add(c1.get(1) + "-" + month);
        if (flag)
        {
          result.append("isnull([")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("],0) as '")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("',");
        }
        else result.append("[")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("],");

        c1.add(2, 1);
      }
    }
    else {
      SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
      int count = getIntervalDaysOfExitDate2(fm.parse(start), fm.parse(end));
      for (int i = 0; i < count; i++)
      {
        c1.add(5, 1);
        String month = String.valueOf(c1.get(2) + 1);
        if (month.length() == 1)
        {
          month = "0" + month;
        }

        String day = String.valueOf(c1.get(5));
        if (day.length() == 1)
        {
          day = "0" + day;
        }
        this.categories.add(c1.get(1) + month + day);
        if (flag)
        {
          result.append("isnull([")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("-")
            .append(day)
            .append("],0) as '")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("-")
            .append(day)
            .append("',");
        }
        else result.append("[")
            .append(c1.get(1))
            .append("-")
            .append(month)
            .append("-")
            .append(day)
            .append("],");
      }

    }

    return result.deleteCharAt(result.length() - 1).toString();
  }

  private static int getIntervalDaysOfExitDate2(Date exitDateFrom, Date exitDateTo)
  {
    Calendar aCalendar = Calendar.getInstance();
    Calendar bCalendar = Calendar.getInstance();
    aCalendar.setTime(exitDateFrom);
    bCalendar.setTime(exitDateTo);
    int days = 0;
    while (aCalendar.before(bCalendar)) {
      days++;
      aCalendar.add(6, 1);
    }
    return days;
  }
}